package com.spring.security.core.validate.sms;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.security.core.properties.SecurityConstants;
import com.spring.security.core.properties.SecurityResponseCode;
import com.spring.security.core.validate.exception.ValidateCodeException;
import com.spring.security.core.validate.impl.AbstractValidateCodeProcessor;
import com.spring.security.core.properties.SecurityProperties;
import com.spring.security.core.support.ServerResponseEntity;
import com.spring.security.core.validate.ValidateCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;

import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

/**
 * 短信验证码处理器
 *
 * @author seabed_moon
 */
@Component("smsValidateCodeProcessor")
public class SmsCodeProcessor extends AbstractValidateCodeProcessor<ValidateCode> {

    private final ObjectMapper objectMapper;

    private final RedisTemplate<String, Object> redisTemplate;
    /**
     * 短信验证码发送器
     */
    private final SmsCodeSender smsCodeSender;

    private final SecurityProperties securityProperties;

    public SmsCodeProcessor(ObjectMapper objectMapper, RedisTemplate<String, Object> redisTemplate, SmsCodeSender smsCodeSender, SecurityProperties securityProperties) {
        this.objectMapper = objectMapper;
        this.redisTemplate = redisTemplate;
        this.smsCodeSender = smsCodeSender;
        this.securityProperties = securityProperties;
    }

    @Override
    protected void send(ServletWebRequest request, ValidateCode validateCode) throws Exception {
        String mobile = validateCode.getMobile();
        if (StringUtils.isEmpty(mobile)) {
            throw new ValidateCodeException("mobile is must be not null");
        }
        HttpServletResponse httpServletResponse = request.getResponse();
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        String smsCheckKey = StringUtils.join(SecurityConstants.SMS_CODE_SEND_CHECK_KEY, mobile);
        if (redisTemplate.hasKey(smsCheckKey)) {
            httpServletResponse.getWriter().write(objectMapper.writeValueAsString(ServerResponseEntity.fail(SecurityResponseCode.SMS_CODE_FREQUENT_REQUESTS, null)));
            return;
        }
        smsCodeSender.send(mobile, validateCode.getCode());
        redisTemplate.opsForValue().set(smsCheckKey, mobile, securityProperties.getCode().getSms().getLimit(), TimeUnit.SECONDS);
        httpServletResponse.getWriter().write(objectMapper.writeValueAsString(ServerResponseEntity.success("", HttpStatus.OK.name())));
    }

}
